'''
This module contains utils functions used by other modules.
'''

from BeautifulSoup import BeautifulSoup, Comment
from blogs.forms import CommentForm
from blogs.models import Blog, Post, Comment, Banned
import blogs.captcha
from django.core.cache import cache
from django.shortcuts import get_object_or_404
from django.conf import settings
from django.contrib.sites.models import Site
import re    
    
def get_response_dict(blog, user, cust_dict):
    '''
        Builds a dictionary to add to the response.
        cust_dict should be in format of {key1: value1, key2: value2, ...}
    '''
    response_dict = {
        'MEDIA_URL': settings.MEDIA_URL,
        'JQUERY_PREFIX': settings.JQUERY_PREFIX,
        'TINY_MCE_PREFIX': settings.TINY_MCE_PREFIX,
        'domain': Site.objects.get_current().domain,
        'is_admin': user.is_authenticated(),
        'blog_name': blog.name,
        'blog_slug': blog.slug,
        'blog_description': blog.description,
        'date_format': blog.date_format,
        'time_format': blog.time_format,
    }
    
    response_dict.update(cust_dict)
    
    return response_dict


def get_cached_object(key, *arguments, **kwargs):
    obj = cache.get(key)
    
    if obj == None:
        obj = get_object_or_404(*arguments, **kwargs)
        cache.set(key, obj, settings.DEFAULT_CACHE_TIME)
     
    return obj

    
def comment_utils(request, blog, post):
    comment_form = None
    new_comment_id = None
    user_ip = ip=request.META.get('REMOTE_ADDR', None)
    
    # Check if user's IP has been banned from this blog
    allowed = not Banned.objects.filter(blog=blog, ip=user_ip)
    
    captcha_error = ''
    
    if allowed and request.method == 'POST':
        
        # Submit new comment
        f = CommentForm(request.POST)
        
        if f.is_valid():
        
            # TODO: implement this captcha field as a custom field widget
            captcha_response = \
                blogs.captcha.submit(request.POST.get('recaptcha_challenge_field', None), 
                request.POST.get('recaptcha_response_field', None),  
                settings.RECAPTCHA_PRIVATE_KEY,  
                request.META.get('REMOTE_ADDR', None))  
            
            if not captcha_response.is_valid:  
                captcha_error = captcha_response.error_code 
                comment_form = f
                
            else:
                comment = f.save(commit=False)
                
                from datetime import datetime
                
                comment.blog = blog
                comment.post = post
                comment.message = sanitize_html(comment.message)
                comment.date = datetime.now()
                comment.ip = user_ip
                
                comment.save()
                cache.delete('Post:%s_comments' % post.slug)
                cache.delete('Blog:%s_latest_comments' % post.blog.slug)
                cache.delete('latest_comments')
                
                new_comment_id = comment.id
        else:
            comment_form = f
    
    # Get comments from cache if it exists
    comments = cache.get('Post:%s_comments' % post.slug)
    
    if comments == None:
        comments = Comment.objects.filter(blog=blog, post=post).order_by('date')
        cache.set('Post:%s_comments' % post.slug, list(comments))
        
    if allowed and post.comments_enabled and comment_form == None:
        comment_form = CommentForm()
        
    return (new_comment_id, comments, comment_form, allowed, user_ip, captcha_error)

def sanitize_html(value):
    '''
    Sanitizes the HTML to remove unwanted elements.
    
    Snippet originally found here: http://www.djangosnippets.org/snippets/205/
    '''
    
    valid_tags = 'i em strong b u a pre'.split()
    valid_attrs = 'href src'.split()
    soup = BeautifulSoup(value)
    for comment in soup.findAll(
        text=lambda text: isinstance(text, Comment)):
        comment.extract()
    for tag in soup.findAll(True):
        if tag.name not in valid_tags:
            tag.hidden = True
        tag.attrs = [(attr, val) for attr, val in tag.attrs
                     if attr in valid_attrs]
                     
    dirty = soup.renderContents().decode('utf8')
    
    # Case insensitive XSS attack vector
    # http://ha.ckers.org/xss.html
    xss = re.compile('j[\s]*(&#x.{1,7})?a[\s]*(&#x.{1,7})?v[\s]*(&#x.{1,7})?a[\s]*(&#x.{1,7})?s[\s]*(&#x.{1,7})?c[\s]*(&#x.{1,7})?r[\s]*(&#x.{1,7})?i[\s]*(&#x.{1,7})?p[\s]*(&#x.{1,7})?t', re.IGNORECASE)
    
    clean = xss.sub('', dirty)
    
    return clean